#ifndef WRAITH_SM_H
#define WRAITH_SM_H

#include <BWAPI.h>

class WraithSM;

class WraithBaseState
{
public:
	WraithBaseState(WraithSM* wk) {wraithSM = wk;}
	virtual ~WraithBaseState() {}

	virtual void enter() = 0;
	virtual void onFrame() = 0;
	virtual void exit() = 0;

	BWAPI::Unit* getUnit();
	BWAPI::Unit* findNearestEnemy();
	WraithSM* findNearestMember();
	std::vector<WraithSM*>& getOtherMembers();

protected:
	WraithSM* wraithSM;
	int exitTimer;
	bool beganTraining;
};

class WraithIdleState : public WraithBaseState
{
public:
	WraithIdleState(WraithSM* wk);
	virtual ~WraithIdleState();

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
	int timeIdling;
};

class WraithWanderState : public WraithBaseState
{
public:
	WraithWanderState(WraithSM* wk);
	virtual ~WraithWanderState();

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
};

class WraithAttackState : public WraithBaseState
{
public:
	WraithAttackState(WraithSM* wk);
	virtual ~WraithAttackState();

	WraithAttackState* reconstruct(BWAPI::Unit* target);

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
	BWAPI::Unit* forceTarget;
};

class WraithFleeState : public WraithBaseState
{
public:
	WraithFleeState(WraithSM* wk);
	virtual ~WraithFleeState();

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
};

class WraithScatterState : public WraithBaseState
{
public:
	WraithScatterState(WraithSM* wk);
	virtual ~WraithScatterState();

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
};

class WraithHoldFlankState : public WraithBaseState
{
public:
	WraithHoldFlankState(WraithSM* wk);
	virtual ~WraithHoldFlankState();

	WraithHoldFlankState* reconstruct(BWAPI::Position pos);
	inline bool isInFlankPosition() {return inFlankPosition;}

	virtual void enter();
	virtual void onFrame();
	virtual void exit();

protected:
	BWAPI::Position flankPos;
	bool inFlankPosition;
};

class WraithSM
{
public:
	WraithSM(BWAPI::Unit* myUnit);
	virtual ~WraithSM();

	virtual void onFrame();
	
	virtual bool expired();

	void changeState(WraithBaseState* state);

	inline BWAPI::Unit* getUnit() const {return myUnit;}
	inline std::vector<WraithSM*>& getOtherMembers() {return otherMembers;}
	inline int getFrameCounter() {return frameCounter;}
	inline WraithWanderState* getWanderState() {return &wanderState;}
	inline WraithIdleState* getIdleState() {return &idleState;}
	inline WraithAttackState* getAttackState() {return &attackState;}
	inline WraithFleeState* getFleeState() {return &fleeState;}
	inline WraithScatterState* getScatterState() {return &scatterState;}

	void SetAttackTile(BWAPI::TilePosition attackTile);
	inline BWAPI::TilePosition GetAttackTile() {return masterAttackTile;}

protected:
	BWAPI::Unit* myUnit;
	BWAPI::Unit* mainTarget;
	BWAPI::TilePosition masterAttackTile;
	std::vector<WraithSM*> otherMembers;
	int frameCounter;

	WraithBaseState* currentState;
	WraithWanderState wanderState;
	WraithIdleState idleState;
	WraithAttackState attackState;
	WraithFleeState fleeState;
	WraithScatterState scatterState;
};

#endif

